Add new function xasprintf for 'buffer-free' printf and alloc (as asprintf,
authoroliskoli <oliskoli>
Tue, 13 Jun 2006 21:48:11 +0000 (21:48 +0000)
committeroliskoli <oliskoli>
Tue, 13 Jun 2006 21:48:11 +0000 (21:48 +0000)
which is not C89 conform).
Split 'init_date_and_time_format' from garmin_txt into
'convert_human_date_format' and 'convert_human_time_format'.

defs.h
util.c

diff --git a/defs.h b/defs.h
index 727f48d1211630b8c0ea7b9c18966746ec071aa1..4a0aff6993b8eb216b9737ccca26b0e4a34cfb88 100644 (file)
--- a/defs.h
+++ b/defs.h
@@ -660,6 +660,7 @@ char *gstrsub(const char *s, const char *search, const char *replace);
 char *xstrrstr(const char *s1, const char *s2);
 void rtrim(char *s);
 char * lrtrim(char *s);
+int xasprintf(char **strp, const char *fmt, ...);
 signed int get_tz_offset(void);
 time_t mkgmtime(struct tm *t);
 time_t current_time(void);
@@ -671,6 +672,8 @@ char * xml_entitize(const char * str);
 char * html_entitize(const char * str);
 char * strip_html(const utf_string*);
 char * strip_nastyhtml(const char * in);
+char * convert_human_date_format(const char *human_datef);     /* "MM,YYYY,DD" -> "%m,%Y,%d" */
+char * convert_human_time_format(const char *human_timef);     /* "HH+mm+ss"   -> "%H+%M+%S" */
 
 /* 
  * Character encoding transformations.
diff --git a/util.c b/util.c
index a728e0008df93a2062530ec906a87713505aeb80..080b555e24d1028e9f0ac8ca5cb50cd306a0a559 100644 (file)
--- a/util.c
+++ b/util.c
@@ -24,6 +24,7 @@
 #include <stdlib.h>
 #include <ctype.h>
 #include <errno.h>
+#include <stdarg.h>
 
 static int i_am_little_endian = -1;
 static int doswap(void);
@@ -281,6 +282,30 @@ xfputs(const char *errtxt, const char *s, FILE *stream)
        }
 }
 
+/*
+ * Allocate a string using a format list with optional arguments
+ */
+
+int
+xasprintf(char **strp, const char *fmt, ...)
+{
+       va_list args;
+       int res;
+       
+       va_start(args, fmt);
+       res = vsnprintf((char *)NULL, 0, fmt, args);
+       *strp = xmalloc(res + 1);
+       va_end(args);
+       
+       va_start(args, fmt);
+       res = vsnprintf(*strp, res + 1, fmt, args);
+       va_end(args);
+
+       is_fatal(res < 0, "(internal): vsnprintf returned %d!", res);
+       
+       return res;
+}
+
 /* 
  * Duplicate a pascal string into a normal C string.
  */
@@ -905,6 +930,165 @@ rot13( const char *s )
        return result;
 }
 
+/*
+ * Convert a human readable date format (i.e. "YYYY/MM/DD") into
+ * a format usable for strftime and others 
+ */
+char *
+convert_human_date_format(const char *human_datef)
+{
+       char *result, *cin, *cout;
+       char prev;
+       int ylen;
+       
+       result = xcalloc((2*strlen(human_datef)) + 1, 1);
+       cout = result;
+       prev = '\0';
+       ylen = 0;
+       
+       for (cin = (char *)human_datef; *cin; cin++)
+       {
+               char okay = 1;
+               
+               if (toupper(*cin) != 'Y') ylen = 0;
+               if (isalpha(*cin)) 
+               {
+                       switch(*cin) 
+                       {
+                       case 'y': case 'Y':
+                               if (prev != 'Y')
+                               { 
+                                       strcat(cout, "%y"); 
+                                       cout += 2;
+                                       prev = 'Y'; 
+                               }
+                               ylen++;
+                               if (ylen > 2) *(cout-1) = 'Y';
+                               break;
+                       case 'm': case 'M':
+                               if (prev != 'M')
+                               {
+                                       strcat(cout, "%m");
+                                       cout += 2;
+                                       prev = 'M';
+                               }
+                               break;
+                       case 'd': case 'D':
+                               if (prev != 'D')
+                               {
+                                       strcat(cout, "%d");
+                                       cout += 2;
+                                       prev = 'D';
+                               }
+                               break;
+                       default:
+                               okay = 0;
+                       }
+               }
+               else if (ispunct(*cin))
+               {
+                       *cout++ = *cin;
+                       prev = '\0';
+               }
+               else okay = 0;
+               
+               is_fatal(okay == 0, "Invalid character \"%c\" in date format!", *cin);
+       }
+       return result;
+}
+
+/*
+ * Convert a human readable time format (i.e. "HH:mm:ss") into
+ * a format usable for strftime and others
+ */
+
+char *
+convert_human_time_format(const char *human_timef)
+{
+       char *result, *cin, *cout;
+       char prev;
+       
+       result = xcalloc((2*strlen(human_timef)) + 1, 1);
+       cout = result;
+       prev = '\0';
+       
+       for (cin = (char *)human_timef; *cin; cin++)
+       {
+               int okay = 1;
+               
+               if (isalpha(*cin))
+               {
+                       switch(*cin)
+                       {
+                       case 'S': case 's':
+                               if (prev != 'S') { 
+                                       strcat(cout, "%S"); 
+                                       cout += 2;
+                                       prev = 'S'; 
+                               }
+                               break;
+                               
+                       case 'M': case 'm':
+                               if (prev != 'M') { 
+                                       strcat(cout, "%M"); 
+                                       cout += 2;
+                                       prev = 'M'; 
+                               }
+                               break;
+                               
+                       case 'h':                               /* 12-hour-clock */
+                               if (prev != 'H') {
+                                       strcat(cout, "%l");     /* 1 .. 12 */
+                                       cout += 2;
+                                       prev = 'H';
+                               }
+                               else *(cout-1) = 'I';           /* 01 .. 12 */
+                               break;
+                               
+                       case 'H':                               /* 24-hour-clock */
+                               if (prev != 'H') {
+                                       strcat(cout, "%k");
+                                       cout += 2;
+                                       prev = 'H';
+                               }
+                               else *(cout-1) = 'H';
+                               break;
+                               
+                       case 'x':
+                               if (prev != 'X') {
+                                       strcat(cout, "%P");
+                                       cout += 2;
+                                       prev = 'X';
+                               }
+                               else *(cout-1) = 'P';
+                               break;
+                               
+                       case 'X':
+                               if (prev != 'X') {
+                                       strcat(cout, "%p");
+                                       cout += 2;
+                                       prev = 'X';
+                               }
+                               else *(cout-1) = 'p';
+                               break;
+                               
+                       default:
+                               okay = 0;
+                       }
+               }
+               else if (ispunct(*cin) || isspace(*cin))
+               {
+                       *cout++ = *cin;
+                       prev = '\0';
+               }
+               else okay = 0;
+               
+               is_fatal(okay == 0, "Invalid character \"%c\" in time format!", *cin);
+       }
+       return result;
+}
+
 /* 
  * Get rid of potentially nasty HTML that would influence another record
  * that includes;